#include "stm32g0xx_hal.h"
#include <string.h>
#include <stdint.h>
#include "mbedtls/sha256.h"
#include <stdio.h>
#include <ctype.h>
#include "flash.h"
#include <stdint.h>

static void transferToPassword(const uint8_t hash[64], uint8_t password[16])
{
	uint8_t indices[16] = {0};
	for (int i = 0; i < 16; i++) {
			uint16_t combined = (hash[i] << 8) | hash[31 - i];
			indices[i] = combined % 64;
	}
	
	for (int i = 0; i < 16; i++) {
			password[i] = hash[indices[i]];
	}
	
	for (int i = 0; i < 16; i++) {
		// ????????????
		uint8_t transform = hash[i] % 8;
		
		switch (transform) {
				case 0: // ???
						password[i] = toupper(password[i]);
						break;
				case 1: // ???
						password[i] = tolower(password[i]);
						break;
				case 2: // ????
						if (password[i] == 'i' || password[i] == 'I') password[i] = '1';
						else if (password[i] == 'o' || password[i] == 'O') password[i] = '0';
						else if (password[i] == 's' || password[i] == 'S') password[i] = '5';
						break;
				case 3: // ??????
						if (password[i] == 'a' || password[i] == 'A') password[i] = '@';
						else if (password[i] == 'c' || password[i] == 'C') password[i] = '(';
						else if (password[i] == 'e' || password[i] == 'E') password[i] = '3';
						break;
				default:
						// ?????
						break;
		}
	}
}

static void bytesToHexString(const uint8_t data[32], char output[65]) 
{
    const char hex_chars[] = "0123456789ABCDEF"; 
    
    for (int i = 0; i < 32; i++) {
        output[i * 2] = hex_chars[(data[i] >> 4) & 0x0F];
        output[i * 2 + 1] = hex_chars[data[i] & 0x0F];
    }
    output[64] = '\0'; 
}

static void getSHA256(const char *input, uint8_t *output)
{
	  mbedtls_sha256_context ctx;
    mbedtls_sha256_init(&ctx);
    
    // ?? SHA-256
    mbedtls_sha256_starts(&ctx, 0); // 0 = SHA-256, 1 = SHA-224
    mbedtls_sha256_update(&ctx, (const uint8_t *)input, strlen(input));
    mbedtls_sha256_finish(&ctx, (uint8_t *)output);
    
    mbedtls_sha256_free(&ctx);
}

void generatePassword(const char *input, uint8_t *password)
{
	uint8_t output[32]  = {0};
	uint8_t textOutput[65] = {0};
	getSHA256(input, output);
	bytesToHexString(output, (char *)textOutput);
	transferToPassword(textOutput, password);
}
